﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Structures;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace X3DXamlXna
{
    static public class Utils
    {
        public static IEnumerable<Vec3Model> buildVec3Model(X3dModel model)
        {
            return (from pts in model.Vertices
                    let trans = Vector3.Transform(pts.Position, model.World)
                    select new Vec3Model(trans, model));
        }
        public static float Variance(IEnumerable<float> vars)
        {
            float mean = vars.Sum() / vars.Count();
            return (from el in vars select (float)Math.Pow((el - mean), 2)).Sum() / vars.Count();
        }

        public static List<X3dModel> intersectModels(BoundingFrustum camera, KDObjects node, GraphicsDevice graphics)
        {
            List<X3dModel> tmp = new List<X3dModel>();
            Queue<KDObjects> S = new Queue<KDObjects>();
            S.Enqueue(node);
            while (S.Count != 0)
            {
                var elem = S.Dequeue();
                if (camera.Intersects(elem._Box))
                {
                    if (elem._isLeaf)
                    {

                        //if (!elem.empty)
                        //{
                        //    Stream str = File.Open("parts\\" + elem.GetHashCode() + ".part", FileMode.Open);
                        //    BinaryFormatter serializer = new BinaryFormatter();
                        //    var Models = serializer.Deserialize(str) as List<X3dModel>;
                        //    str.Close();
                        //    foreach (var model in Models)
                        //    {
                        //        model.BuildIndexBuffer(graphics);
                        //        model.BuildVertexBuffer(graphics);
                        //    }

                        tmp.AddRange(elem.Models);
                        //}
                    }
                    else
                    {
                        //if (!elem.empty)
                        //{
                        //    Stream str = File.Open("parts\\" + elem.GetHashCode() + ".part", FileMode.Open);
                        //    BinaryFormatter serializer = new BinaryFormatter();
                        //    var Models = serializer.Deserialize(str) as List<X3dModel>;
                        //    str.Close();
                        //    foreach (var model in Models)
                        //    {
                        //        model.BuildIndexBuffer(graphics);
                        //        model.BuildVertexBuffer(graphics);
                        //    }

                        tmp.AddRange(elem.Models);
                        //}
                        S.Enqueue(elem.left);
                        S.Enqueue(elem.right);
                    }
                }
            }
            return tmp;
            //if (node == null) return;
            //if (camera.Intersects(node._Box))
            //{
            //    if (node._isLeaf)
            //    {
            //        modelToDraw.AddRange(((KDLeaf)node).models);
            //        return;

            //    }
            //    intersectModels(camera, ((KDNode)node).left, modelToDraw);
            //    intersectModels(camera, ((KDNode)node).right, modelToDraw);
            //}
        }
        public static VertexPositionNormalTexture[] createArray(string points, string normals)
        {
            string[] pots = points.Split(new string[] { ", ", "  ", "   ", "    ", "     ", "      ", "       ", "        ", "         ", "          ", "           ", "           ", "           ", "            ", "             ", "              " }, StringSplitOptions.RemoveEmptyEntries);

            string[] ns = normals.Split(new string[] { ", ", "  ", "   ", "    ", "     ", "      ", "       ", "        ", "         ", "          ", "           ", "           ", "           ", "            ", "             ", "              " }, StringSplitOptions.RemoveEmptyEntries);

            var pts = (from el in pots select createVector(el)).ToArray();
            var nrmls = (from el in ns select createVector(el)).ToArray();

            //var rnd = new Random();

            //nrmls =
            //    (from norm in nrmls
            //     let nnorm = new Vector3((float)(norm.X * rnd.NextDouble() + .001), (float)(norm.Y * rnd.NextDouble() + .001), (float)(norm.Z * rnd.NextDouble() + .001))
            //     select nnorm).ToArray();
            //foreach (var n in nrmls) n.Normalize();

            return (from ind in Enumerable.Range(0, pts.Length)
                    let point = pts[ind]
                    let norm = nrmls[ind]
                    select new VertexPositionNormalTexture(point, norm, Vector2.Zero)).ToArray();
        }
        public static Vector3 createVector(string s)
        {
            string[] scoords = s.Split(new string[] { ",", " ", "  ", "   ", "    ", "     ", "      ", "       ", "        ", "         ", "          ", "           ", "           ", "           ", "            ", "             ", "              " }, StringSplitOptions.RemoveEmptyEntries);
            float[] coords = (from c in scoords select float.Parse(c, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture)
                                ).ToArray();
            return new Vector3(coords[0], coords[1], coords[2]);
        }

        public static Int16[] createIndices(string ind)
        {

            string[] Tind = ind.Split(new string[] { ",", " ", "  ", "   ", "    ", "     ", "      ", "       ", "        ", "         ", "          ", "           ", "           ", "           ", "            ", "             ", "              " }, StringSplitOptions.RemoveEmptyEntries);
            return (from el in Tind
                    let i = Int16.Parse(el)
                    where i >= 0
                    select i).ToArray();
        }
        public static Vector4 setToVector4(string p)
        {
            string[] vector = p.Split(new char[] { ' ' });
            float P0 = float.Parse(vector[0], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture);
            float P1 = float.Parse(vector[1], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture);
            float P2 = float.Parse(vector[2], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture);
            float P3 = float.Parse(vector[3], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture);
            return new Vector4(P0, P1, P2, P3);
        }

        public static Vector3 setToVector3(string p)
        {
            string[] vector = p.Split(new char[] { ' ' });
            float P0 = float.Parse(vector[0], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture);
            float P1 = float.Parse(vector[1], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture);
            float P2 = float.Parse(vector[2], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture);
            return new Vector3(P0, P1, P2);
        }



        public static Vector3 setToVector3Scale(string p)
        {
            if (p != null)
                return setToVector3(p);
            else
                return new Vector3(1, 1, 1);
        }
        public static Vector3 setToVector3Translation(string p)
        {
            if (p != null)
                return setToVector3(p);
            else
                return new Vector3(0, 0, 0);
        }
        public static Vector4 setToVector4Rotation(string p)
        {
            if (p != null)
                return setToVector4(p);
            else
                return new Vector4(0, 0, 1, 0);
        }        
    }
}
